﻿using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.Filters;
using MiniFox.Caching;
using MiniFox.Configurations;
using MiniFox.Infrastructure;
using MiniFox.Platform.Configurations;
using MiniFox.Platform.Exceptions;
using MiniFox.Web;

namespace MiniFox.Platform.Web.Filters
{
    /// <summary>
    /// 验证码校验拦截
    /// </summary>
    public class VerifyAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        public VerifyAttribute()
        {
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnActionExecuting(ActionExecutingContext actionContext)
        {
            var config = ConfigurationFactory.GetConfig<VerifyConfiguration>();
            if (config == null || config.VerifySettings.Count <= 0)
                return;

            var request = actionContext.HttpContext.Request;

            string path = request.Path.ToString().ToLower();
            var setting = config.VerifySettings[path];

            if (setting == null || !setting.Enabled)
                return;

            var ticket = request.Headers[GlobalKey.VALID_TICKET];

            if (string.IsNullOrWhiteSpace(ticket))
            {
                ticket = request.Query[GlobalKey.VALID_TICKET];
            }
            if (string.IsNullOrWhiteSpace(ticket))
            {
                throw new PlatformException("MSG_InvalidTicket");
            }

            if (setting.RetryTimes > 0)
            {
                string key = $"{request.GetClientIP()}-{ticket}";
                var cacheProvider = CacheService.DefaultCachingProvider;
                int retryTimes = 0;
                if (cacheProvider.Contains(key))
                {
                    retryTimes = cacheProvider.Get<int>(key);//取计数值
                }
                retryTimes++;//更新计数
                cacheProvider.Add(key, retryTimes);//

                if (retryTimes <= setting.RetryTimes)//重试次数小于重试临界值时直接返回
                {
                    return;
                }
            }

            Response response;
            if (setting.Async)//异步模式下，二段验票
            {
                //发送到远程验证
                response = new Uri(config.CheckResultUrl).HttpGet<Response>(new { ticket });
            }
            else //同步模式下，从QueryString或HttpHeader中提取验证码，并发送到
            {
                var validCode = request.Query[GlobalKey.VALID_CODE];
                if (string.IsNullOrWhiteSpace(validCode))
                {
                    validCode = request.Headers[GlobalKey.VALID_CODE];//http头部提取
                }
                var query = new
                {
                    ticket,
                    code = validCode
                };

                //发送到远程验证
                response = new Uri(config.MatchCodeUrl).HttpGet<Response>(query);
            }

            if (response == null || !response.Success)
                throw new PlatformException("MSG_UnmatchedValidCode");
        }
    }
}
